﻿using System;
using System.Diagnostics.Contracts;
using FlitBit.Cache.CodeContracts;

namespace FlitBit.Cache
{
	/// <summary>
	///   Interface for cache eviction managers.
	/// </summary>
	[ContractClass(typeof(ContractForICacheEvictionManager)), DefaultCacheEvictionManager]
	
	public interface ICacheEvictionManager
	{
		/// <summary>
		///   Adds an eviction callback to be run on then next
		///   eviction cycle.
		/// </summary>
		/// <param name="callback">
		///   Callback function taking a boolean
		///   and returning a boolean. The parameter indicates whether
		///   the call is synchrounous, the result indicates whether
		///   the callback should be rescheduled.
		/// </param>
		void AddEvictionCallback(Func<bool, bool> callback);

		/// <summary>
		///   Adds an eviction monitor.
		/// </summary>
		/// <param name="monitor">the monitor</param>
		void AddEvictionMonitor(ICacheEvictionMonitor monitor);

		/// <summary>
		///   Removes an eviction monitor.
		/// </summary>
		/// <param name="key">the monitor's key</param>
		void RemoveEvictionMonitor(Guid key);
	}

	namespace CodeContracts
	{
		/// <summary>
		///   CodeContracts Class for ICacheEvictionManager
		/// </summary>
		[ContractClassFor(typeof(ICacheEvictionManager))]
		internal abstract class ContractForICacheEvictionManager : ICacheEvictionManager
		{
			#region ICacheEvictionManager Members

			/// <summary>
			/// </summary>
			/// <param name="monitor"></param>
			public void AddEvictionMonitor(ICacheEvictionMonitor monitor)
			{
				Contract.Requires<ArgumentNullException>(monitor != null);

				throw new NotImplementedException();
			}

			/// <summary>
			/// </summary>
			/// <param name="key"></param>
			public void RemoveEvictionMonitor(Guid key)
			{
				Contract.Requires<ArgumentNullException>(key != Guid.Empty);

				throw new NotImplementedException();
			}

			/// <summary>
			/// </summary>
			/// <param name="callback"></param>
			public void AddEvictionCallback(Func<bool, bool> callback)
			{
				Contract.Requires<ArgumentNullException>(callback != null);

				throw new NotImplementedException();
			}

			#endregion
		}
	}
}